package com.beta.user.auth.center.service.provider;

import com.alibaba.cloudapi.sdk.constant.SdkConstant;
import com.alibaba.cloudapi.sdk.enums.HttpMethod;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.beta.cat.service.RedissonService;
import com.beta.user.auth.center.api.request.BetaUsersRegisterReq;
import com.beta.user.auth.center.api.response.BetaUsersRegisterResp;
import com.beta.user.auth.center.api.response.CommonResultEnum;
import com.beta.user.auth.center.api.service.IRPCBetaUsersRegister;
import com.beta.user.auth.center.service.constant.BusinessConstant;
import com.beta.user.auth.center.service.dto.SaaSResponse;
import com.beta.user.auth.center.service.mapper.model.BetaUserRegisterRecord;
import com.beta.user.auth.center.service.service.IBetaUsersRegisterRecordService;
import com.beta.user.auth.center.service.utils.SaaSApiUtil;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;

/**
 * @author gwqin
 * @description
 * @date 2023-06-29 16:27
 */
@Slf4j
@DubboService
@Service
public class RPCBetaUsersRegisterImpl implements IRPCBetaUsersRegister {

    @Autowired
    private RedissonService redissonService;

    @Autowired
    private IBetaUsersRegisterRecordService registerRecordService;

    private static final String userNmae = "阳光小顾";
    @Override
    public BetaUsersRegisterResp betaUsersRegister(BetaUsersRegisterReq request) {
        BetaUsersRegisterResp resp = new BetaUsersRegisterResp();
        String userId = request.getUserId();
        if (StringUtil.isEmpty(userId)) {
            resp.setResult(CommonResultEnum.MISSING_REQUEST_PARAMETER);
            resp.setSuccess(false);
            return resp;
        }

        // 先查本地表判断是否已经注册
        if (judgeRegistered(userId)) {
            resp.setSuccess(true);
            return resp;
        }

        String lockKey = String.format(BusinessConstant.BETA_USER_REGISTER_LOCK_KEY, userId);
        try {
            /**
             * 锁粒度：用户级锁，防止同一个用户出现多次注册情况
             * 锁持有时间：5s（5s内能完成注册及数据保存）
             * 锁等待时间：5s，需要等到上一个完成后再继续执行
             */
            if (redissonService.tryLock(lockKey, BusinessConstant.BETA_USER_REGISTER_LOCK_TIME, BusinessConstant.BETA_USER_REGISTER_LOCK_TIME)
                    && (judgeRegistered(userId) || saasRegister(request))) {
                // 二次查本地表判断是否已经注册
                resp.setSuccess(true);
                return resp;
            }
        } catch (Exception e) {
            log.error("BETA SAAS 用户注册出错，userId：{}，错误信息是:{}", userId, e.getMessage(), e);
        } finally {
            redissonService.unlock(lockKey);
        }

        resp.setResult(CommonResultEnum.SYSTEM_HAS_MALFUNCTIONED);
        resp.setSuccess(false);
        return resp;
    }

    /**
     * 调用SAAS接口进行用户注册
     *
     * @param request
     * @return
     */
    private boolean saasRegister(BetaUsersRegisterReq request) {
        //获取基金经理姓名的数字最大值
        Integer maxNameNumber = getMaxNameNumber();
        if (maxNameNumber == null) {
            log.error("获取基金经理名称为null");
            return false;
        }
        request.setUserName(userNmae + String.format("%06d", maxNameNumber));
        // 调用阿里网关进行注册
        String params = JSON.toJSONString(request);
        byte[] postBody = params.getBytes(SdkConstant.CLOUDAPI_ENCODING);
        SaaSResponse response = SaaSApiUtil.requestSaaSApi(HttpMethod.POST_BODY, "/API/BetaUsersRegister", new HashMap<>(0), postBody);

        String responseBody = null;
        if (response == null
                || !response.isSuccess()
                || StringUtils.isEmpty(response.getResponseBody())) {
            log.error("调用阿里API网关进行用户注册失败，请求参数：{}，返回内容：{}", JSON.toJSONString(request), JSON.toJSONString(response));
            return false;
        }

        responseBody = response.getResponseBody();
        Boolean success = JSON.parseObject(responseBody).getBoolean("Data");
        if (Boolean.FALSE.equals(success)) {
            log.error("调用阿里API网关进行用户注册失败，请求参数：{}，返回内容：{}", JSON.toJSONString(request), JSON.toJSONString(response));
            return false;
        } else {
            // 保存到本地表中
            BetaUserRegisterRecord registerRecord = new BetaUserRegisterRecord()
                    .setBetaUserId(request.getUserId())
                    .setBetaUserNameNumber(maxNameNumber)
                    .setRegistered(BusinessConstant.BETA_USER_REGISTER_FLAG);
            registerRecordService.save(registerRecord);
        }
        return true;
    }

    /**
     * 判断用户是否已注册过
     *
     * @param userId
     * @return
     */
    private boolean judgeRegistered(String userId) {
        LambdaQueryWrapper<BetaUserRegisterRecord> queryWrapper = new LambdaQueryWrapper<BetaUserRegisterRecord>()
                .eq(BetaUserRegisterRecord::getBetaUserId, userId)
                .eq(BetaUserRegisterRecord::getRegistered, BusinessConstant.BETA_USER_REGISTER_FLAG)
                .last(" LIMIT 1");
        BetaUserRegisterRecord registerRecord = registerRecordService.getOne(queryWrapper);
        boolean result = registerRecord != null && registerRecord.getRegistered() == BusinessConstant.BETA_USER_REGISTER_FLAG;
        log.info("用户（{userId}）已注册情况：{}", result);
        return result;
    }

    /**
     * 获取当前名称中最大的数字，返回时加1
     *
     * @return
     */
    private Integer getMaxNameNumber() {
        LambdaQueryWrapper<BetaUserRegisterRecord> queryWrapper = new LambdaQueryWrapper<BetaUserRegisterRecord>()
                .orderByDesc(BetaUserRegisterRecord::getBetaUserNameNumber)
                .last(" LIMIT 1");
        BetaUserRegisterRecord registerRecord = registerRecordService.getOne(queryWrapper);
        log.info("基金经理名称最大值：{}", registerRecord);
        if (registerRecord == null) {
            log.error("获取基金经理名称为null");
            return null;
        }
        if (registerRecord.getBetaUserNameNumber() == null) {
            return 1;
        }
        return registerRecord.getBetaUserNameNumber() + 1;
    }
}
